//
//  AudioManager.swift
//  AudioToolProject
//
//  Created by 邹琳 on 2019/5/5.
//  Copyright © 2019 邹琳. All rights reserved.
//

import Foundation
import AVFoundation

func get_audio_name(_ format:String) -> String{
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyyMMddHHmmss"
    let tempTime = formatter.string(from: Date())
    
    let fileName = tempTime+format
    
    guard let filePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last else{
        return ""
    }
    
    return filePath + "/" + fileName
}

func get_audio_time(audioPath:String) -> String{
    let url = URL(fileURLWithPath: audioPath)
    do{
    	let palyer = try AVAudioPlayer(contentsOf: url)
        let duration = Int(palyer.duration)
        let res = String(format: "%02ld:%02ld", Int(duration / 60), Int(duration) % 60)
        return res
    }catch{
        print(error)
        return "00:00"
    }
}


/** 音频的剪切 */
func audio_cut(_ audioPath:URL,startTime:Int,endTime:Int,finish:@escaping((String)->Void)){
    let outputPath = get_audio_name(".m4a")
    let outputUrl = URL(fileURLWithPath: outputPath)
    /** 防止路径重复 */
    try? FileManager.default.removeItem(at: outputUrl)
    
    /** 初始化要剪切的音频文件 */
    let asset = AVAsset(url: audioPath)
    let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A)
    
    /** 前切的时间段 */
    let timeRange = CMTimeRangeFromTimeToTime(start: CMTime(value: CMTimeValue(startTime), timescale: 1), end: CMTime(value: CMTimeValue(endTime), timescale: 1))
    
    /** 音频导出 */
    exportSession?.outputURL = outputUrl
    exportSession?.outputFileType = AVFileType.m4a
    exportSession?.timeRange = timeRange
    
    exportSession?.exportAsynchronously(completionHandler: {
        if exportSession?.status == AVAssetExportSession.Status.completed{
            finish(outputPath)
        }else{
            finish("")
            print("error = \(exportSession?.error?.localizedDescription ?? "音频前切失败")")
        }
    })
}

/** 音频的淡入淡出 */
func audio_fadeInout(_ audioPath:URL,fadeInTime:Int,fadeOutTime:Int,finish:@escaping((String)->Void)){
    let exportPath = get_audio_name(".m4a")
    let exportPathURL = URL(fileURLWithPath: exportPath)
    /** 删除相同路径 */
    try? FileManager.default.removeItem(at: exportPathURL)
    
    /** 创建音频合成器 */
    let mixComposition = AVMutableComposition()
    let audioAsset = AVURLAsset(url: audioPath)
    /** 获取音频的时长 */
    let audioTimeRange = CMTimeRangeMake(start: CMTime.zero, duration: audioAsset.duration)
    
    //创建倒出音频
    let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetAppleM4A)
    assetExport?.outputURL = exportPathURL
    assetExport?.outputFileType = AVFileType.m4a
    assetExport?.shouldOptimizeForNetworkUse = true
    
    /** 获取音频轨道 */
    guard let audioTrack = audioAsset.tracks(withMediaType: AVMediaType.audio).first else{
        return
    }
    /** 创建音频容器 */
    let audioCompositionTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
    /** 插入音频到容器 */
    try? audioCompositionTrack?.insertTimeRange(audioTimeRange, of: audioTrack, at: CMTime.zero)
    
    
    /** 初始化音频混合器 */
    let exportAudioMix = AVMutableAudioMix()
    guard let mixCompositionTrack = mixComposition.tracks(withMediaType: AVMediaType.audio).first else{
        return
    }
    
    let exportAudioMixInputParams = AVMutableAudioMixInputParameters(track: mixCompositionTrack)
    
    /** 设置淡入淡出 */
    let volume = AVAudioSession.sharedInstance().outputVolume
    if fadeInTime > 0{
        let continueFadeInTime = CMTimeMake(value: Int64(fadeInTime), timescale: 1)
        exportAudioMixInputParams.setVolumeRamp(fromStartVolume: 0, toEndVolume: volume, timeRange: CMTimeRangeMake(start: CMTime.zero, duration: continueFadeInTime))
    }
    
    if fadeOutTime > 0{
        let continueFadeOutTime = CMTimeMake(value: Int64(fadeOutTime), timescale: 1)
        let fadeoutStarttime = CMTimeSubtract(audioAsset.duration, continueFadeOutTime)
        exportAudioMixInputParams.setVolumeRamp(fromStartVolume: volume, toEndVolume: 0, timeRange: CMTimeRangeMake(start: fadeoutStarttime, duration: continueFadeOutTime))
    }
    
    let audioMixParams = [exportAudioMixInputParams]
    exportAudioMix.inputParameters = audioMixParams
    /** 添加到导出配置 */
    assetExport?.audioMix = exportAudioMix
    /** 开始导出 */
    assetExport?.exportAsynchronously(completionHandler: {
        if assetExport?.status == AVAssetExportSession.Status.completed{
            finish(exportPath)
        }else{
            finish("")
            print("error = \(assetExport?.error?.localizedDescription ?? "音频前切失败")")
        }
    })
}

/** 背景音乐合成 */
func audio_back_music(_ audioPath:URL,back_audio:URL,finish:@escaping((String)->Void)){
    
    let outputPath = get_audio_name(".m4a")
    let outputPathURL = URL(fileURLWithPath: outputPath)
    
    /** 删除相同路径 */
    try? FileManager.default.removeItem(at: outputPathURL)
    
	// 创建媒体组合器
    let mixComposition = AVMutableComposition()
    /** 初始化音频 */
    let audioAsset = AVURLAsset(url: audioPath)
    let audioBackAsset = AVURLAsset(url: back_audio)
    
    /** 音乐时间 */
    let audioTimeRange = CMTimeRangeMake(start: CMTime.zero, duration: audioAsset.duration)
    /** 获取媒体文件中的轨道 */
    guard let audioTrack = audioAsset.tracks(withMediaType: AVMediaType.audio).first else {
        return
    }
    
    //添加一个音频通道
    let audioCompositionTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
    try? audioCompositionTrack?.insertTimeRange(audioTimeRange, of: audioTrack, at: CMTime.zero)
    
    /** 获取背景音乐的时间 */
    let audio_duration = Int(audioAsset.duration.value)
    var begin_time = 0
    var beginTime = CMTime.zero
    
    while begin_time < audio_duration {
        guard let audioBackTrack = audioBackAsset.tracks(withMediaType: AVMediaType.audio).first else{
            return
        }
        let audioCompositionBacktrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)
        try? audioCompositionBacktrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: audioBackAsset.duration), of: audioBackTrack, at: beginTime)
        begin_time += Int(audioBackAsset.duration.value)
        beginTime = CMTimeAdd(beginTime, audioBackAsset.duration)
    }
    
    //初始化音频混合器
    let exportAudioMix = AVMutableAudioMix()
    var arrayAudioMixParams:[AVMutableAudioMixInputParameters] = []
    /** 设置背景音乐的d声音 */
    var isSet = true
    mixComposition.tracks(withMediaType: AVMediaType.audio).forEach { (track) in
        if(isSet){
            
        }else{
            let exportAudioMixInputParams = AVMutableAudioMixInputParameters(track: track)
            exportAudioMixInputParams .setVolumeRamp(fromStartVolume: AVAudioSession.sharedInstance().outputVolume * 0.3, toEndVolume: AVAudioSession.sharedInstance().outputVolume * 0.3, timeRange: CMTimeRangeMake(start: CMTime.zero, duration: track.asset?.duration ?? CMTime.zero))
            arrayAudioMixParams.append(exportAudioMixInputParams)
            isSet = false
        }
    }
    
    exportAudioMix.inputParameters = arrayAudioMixParams
    
    
    //创建合成输出
    let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetAppleM4A)
    assetExport?.outputURL = outputPathURL
    assetExport?.outputFileType = AVFileType.m4a
    assetExport?.shouldOptimizeForNetworkUse = true
    assetExport?.audioMix = exportAudioMix
    assetExport?.exportAsynchronously(completionHandler: {
        if assetExport?.status == AVAssetExportSession.Status.completed{
            finish(outputPath)
        }else{
            finish("")
            print("error = \(assetExport?.error?.localizedDescription ?? "音频前切失败")")
        }
    })
}


//MARK:-----------从-iTunes导入歌曲------------//
func import_audio_fromiTunes(_ url:URL,finish:@escaping((String)->Void)){
    let asset = AVURLAsset(url: url)
    guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else {
        finish("")
        return
    }
    
    let exportPath = get_audio_name(".m4a")
    let exportUrl = URL(fileURLWithPath: exportPath)
    exporter.outputURL = exportUrl
    exporter.outputFileType = .m4a
    exporter.exportAsynchronously {
        if exporter.status == AVAssetExportSession.Status.completed{
            finish(exportPath)
        }else{
            finish("")
            print("error = \(exporter.error?.localizedDescription ?? "音频前切失败")")
        }
    }
}


